﻿
// DBBrowserDoc.h: CDBBrowserDoc 类的接口
//


#pragma once

#include "pch.h"

struct _TASK
{
	size_t total = 0;
	int tasks = 0;
	time_t begin = clock();
	time_t end;
	bool fresh = false;
	std::vector<size_t> comp;
};

class CDBBrowserDoc : public CDocument
{
protected: // 仅从序列化创建
	CDBBrowserDoc() noexcept;
	DECLARE_DYNCREATE(CDBBrowserDoc)

// 特性
public:
	int m_pagesize = 10000;
	std::map<int, std::vector<std::vector<std::wstring>>> m_data;
	CWinThread *m_datathread = nullptr;
	std::string m_sql_select = "";
	std::string m_sql_where = "";
	std::string m_sql_order = "";
	std::string m_sql = "";
	std::string lastsql = "";
	sqlite::database m_db;
	std::map<CString, std::vector<std::wstring>> m_tree;
	time_t m_time = 0;
	int m_rowid = -1;
	int m_pyjp = -1;
	int m_columncount = 0;
	int m_rowcount = 0;
	int m_itemcount = 0;
	bool m_transaction = false;
	bool m_autotrans = true;
	bool m_slowmode = true;
	char m_newrow = 0;
	CString m_table = _T("");
	std::wstring m_root;
	std::wstring m_tbl;
	_TASK *m_task = nullptr;
	cppjieba::MixSegment *m_jieba = nullptr;
	Hanzi::CodeGenerater *m_codegen = nullptr;

// 操作
public:
	void databaseadapter(std::u16string usql, bool colinfo = true);
	void databaseadapter(std::wstring wsql, bool colinfo = true);
	void databaseadapter(std::string sql, bool colinfo = true);

// 重写
public:
	//virtual BOOL OnNewDocument();
	virtual void Serialize(CArchive& ar);
#ifdef SHARED_HANDLERS
	virtual void InitializeSearchContent();
	virtual void OnDrawThumbnail(CDC& dc, LPRECT lprcBounds);
#endif // SHARED_HANDLERS

// 实现
public:
	virtual ~CDBBrowserDoc();
#ifdef _DEBUG
	virtual void AssertValid() const;
	virtual void Dump(CDumpContext& dc) const;
#endif

protected:

// 生成的消息映射函数
protected:
	DECLARE_MESSAGE_MAP()

#ifdef SHARED_HANDLERS
	// 用于为搜索处理程序设置搜索内容的 Helper 函数
	void SetSearchContent(const CString& value);
#endif // SHARED_HANDLERS
public:
	void GetPageData();
	void Cleartblinfo();
	void LoadDictFromRes(WORD ID);
	cppjieba::MixSegment * GetJieba();
	std::string trad2simp(std::string str);
	bool IsGB2312(std::string word);
	std::wstring GetDefaultCreateSQL(CString &table, bool default = true);
};

struct _EXPORTDB
{
	CDBBrowserDoc *pDoc;
	CString sql;
	CString path;
	char delimiter = '\t';
	bool utf16 = false;
	int taskid;
};

struct _IMPORTDB
{
	CDBBrowserDoc *pDoc;
	CString sql;
	CString path;
	bool duoyi = false;
	bool pinyin = false;
	char keyindex = 0;
	char valueindex = 0;
	std::string default = "";
	char delimiter = '\t';
	char quote_character = '"';
	int CRLF = 1;
	bool first_row_is_header = false;
	Hanzi::CodeGenerater *pGen = nullptr;
	int taskid;
};

UINT GetPageDataByThread(LPVOID lp);

UINT ExportTableToFileByThread(LPVOID lp);

UINT ImportTableByThread(LPVOID lp);

template<typename T, typename TS>
void _import_template(_IMPORTDB *pinfo, const char *data, size_t size);
template<> void _import_template<char, std::wstring>(_IMPORTDB *pinfo, const char *data, size_t size);

template<typename T>
void _ImportLine_gen(sqlite::database_binder &p, std::vector<T> &rowdata, int &paras, _IMPORTDB *pinfo) {
	std::vector<T> Codes = pinfo->pGen->GetCode(rowdata[pinfo->valueindex]);
	for (size_t i = 0; i < Codes.size(); i++) {
		rowdata[pinfo->keyindex] = Codes[i];
		for (int i = 0; i < paras; i++) { p << rowdata[i]; }
		p++;
	}
}
template<typename T>
void _ImportLine_py_gen(sqlite::database_binder &p, std::vector<T> &rowdata, int& paras, _IMPORTDB *pinfo) {
	std::vector<T> Codes = pinfo->pGen->GetCode(rowdata[pinfo->valueindex]);
	for (size_t i = 0; i < Codes.size(); i++) {
		rowdata[pinfo->keyindex] = Codes[i];
		rowdata[paras - 1] = dbother::getpyszm(Codes[i]);
		for (int i = 0; i < paras; i++) { p << rowdata[i]; }
		p++;
	}
}
template<typename T>
void _ImportLine(sqlite::database_binder &p, std::vector<T> &rowdata, int &paras, _IMPORTDB *pinfo) {
	for (int i = 0; i < paras; i++) { p << rowdata[i]; }
	p++;
}
template<typename T>
void _ImportLine_py(sqlite::database_binder &p, std::vector<T> &rowdata, int& paras, _IMPORTDB *pinfo) {
	rowdata[paras - 1] = dbother::getpyszm(rowdata[pinfo->keyindex]);
	for (size_t i = 0; i < paras; i++) { p << rowdata[i]; }
	p++;
}
template<typename T>
void _ImportLine_duoyi(sqlite::database_binder &p, std::vector<T> &rowdata, int &paras, _IMPORTDB *pinfo) {
	size_t len = rowdata.size();
	for (int i = 1; i < len; i++) {
		p << rowdata[0]
			<< rowdata[i]
			<< len - i;
		p++;
	}
}
template<typename T>
void _ImportLine_duoyi_py(sqlite::database_binder &p, std::vector<T> &rowdata, int& paras, _IMPORTDB *pinfo) {
	int len = rowdata.size();
	T szm = dbother::getpyszm(rowdata[pinfo->keyindex]);
	for (int i = 1; i < len; i++) {
		p << rowdata[0]
			<< rowdata[i]
			<< len - i
			<< szm;
		p++;
	}
}